package com.hoshiicloud.payment.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.hoshiicloud.payment.vo.EncryptedResponse;
import com.hoshiicloud.payment.util.aesrsa.AES;
import com.hoshiicloud.payment.util.aesrsa.ConvertUtils;
import com.hoshiicloud.payment.util.aesrsa.EncryUtil;
import com.hoshiicloud.payment.util.aesrsa.RSA;
import com.hoshiicloud.payment.util.aesrsa.SecureRandomUtil;
import java.util.Map;
import java.util.TreeMap;
import lombok.extern.slf4j.Slf4j;

/**
 * @program: hoshiicloud
 * @description: 加解密工具类
 * @author: Mr.wu
 * @create: 2019-06-03 09:42
 **/
@Slf4j
public class EncryptionUtil {

    /**
     * @param param
     * @return com.hoshiicloud.payment.vo.EncryptedResponse
     * @author: Mr.wu
     * @descripton:使用aes+rsa加密数据,返回加密数据实体,需先配置rsa密钥
     * @date: 17:50 2019/5/27
     */
    public static EncryptedResponse encryptData(Object param, String clientPrivateKey,
            String serverPublicKey) throws Exception {
        TreeMap<String, Object> paramMap = JSONObject.parseObject(JSON.toJSONString(param),
                new TypeReference<TreeMap<String, Object>>() {
                });
        // 生成RSA签名
        String sign = EncryUtil.handleRSA(paramMap, clientPrivateKey);
        paramMap.put("sign", sign);

        String info = JSON.toJSONString(paramMap);
        //随机生成AES密钥
        String aesKey = SecureRandomUtil.getRandom(16);
        //AES加密数据
        String data = AES.encryptToBase64(ConvertUtils.stringToHexString(info), aesKey);

        // 使用RSA算法将商户自己随机生成的AESkey加密
        String encryptkey = RSA.encrypt(aesKey, serverPublicKey);
        EncryptedResponse encryptedResponse = new EncryptedResponse();
        encryptedResponse.setData(data);
        encryptedResponse.setEncryptKey(encryptkey);
        log.debug("加密后的请求数据:" + encryptedResponse.toString());
        return encryptedResponse;
    }

    /**
     * @param jsonCipher 请求体json字符串
     * @return java.util.Map<java.lang.String, java.lang.String>
     * @author: Mr.wu
     * @descripton: 解密使用aes+rsa加密的数据,返回数据map,需先配置rsa密钥,如验签失败返回空
     * @date: 15:42 2019/6/1
     */
    public static Map<String, String> decryptData(String jsonCipher, String clientPublicKey,
            String serverPrivateKey) throws Exception {
        EncryptedResponse req = JSON.parseObject(jsonCipher, EncryptedResponse.class);
        // 验签
        boolean passSign = EncryUtil.checkDecryptAndSign(req.getData(),
                req.getEncryptKey(), clientPublicKey, serverPrivateKey);

        if (passSign) {
            // 验签通过
            String aeskey = RSA.decrypt(req.getEncryptKey(),
                    serverPrivateKey);
            String data = ConvertUtils.hexStringToString(AES.decryptFromBase64(req.getData(),
                    aeskey));
            log.info("解密后的明文:" + data);
            return JSON.parseObject(data, Map.class);
        } else {
            log.info("验签失败");
        }
        return null;
    }
}
